package main

import (
	"fmt"
	"os"
	"runtime"
	"strings"

	"github.com/cn-zhangjie/postgresql-to-struct/dao"
	"github.com/cn-zhangjie/postgresql-to-struct/pkg/database"
	"github.com/cn-zhangjie/postgresql-to-struct/pkg/settings"
	"github.com/cn-zhangjie/postgresql-to-struct/pkg/utils"
	"github.com/cn-zhangjie/postgresql-to-struct/po"
)

func main() {
	// 关闭数据库
	defer database.Close()
	// 获得所有表
	tableInfoSlice := dao.FindAllTableInfo()
	for _, item := range tableInfoSlice {
		// 开始逐个获得每个表的详情结构
		tableColumnSlice := dao.FindOneByTableName(item.Name)
		writeOne(item, tableColumnSlice)
	}
}

// 写文件
// 以表名为.go的文件名和结构体名，如果是以t_开头，则去掉
func writeOne(tableInfo po.TableInfo, tableColumnSlice []po.TableColumn) {

	// 表名
	tableName := tableInfo.Name
	// 设置中的表前缀
	tableNamePre := settings.DatabaseSetting.TableNamePre

	// 从配置里获得保存的文件夹
	saveDir := settings.OutPutSetting.SaveDir
	fileName := utils.DelPre(tableName, tableNamePre)
	// 存储路径
	var savePathBuilder strings.Builder
	savePathBuilder.WriteString(saveDir)
	// 不同平台的分隔符不一样
	sysType := runtime.GOOS
	if sysType == "windows" {
		savePathBuilder.WriteString("\\")
	} else {
		savePathBuilder.WriteString("/")
	}

	savePathBuilder.WriteString(fileName)
	savePathBuilder.WriteString(".go")
	// 创建文件
	file, err := os.Create(savePathBuilder.String())
	if err != nil {
		fmt.Println("创建.go文件失败：", err)
		return
	}

	// 文件创建完了，开始拼接往里面写入字符
	var writeBuilder strings.Builder

	// 包名
	packageName := settings.OutPutSetting.PackageName
	if packageName != "" {
		writeBuilder.WriteString("package ")
		writeBuilder.WriteString(packageName)
		writeBuilder.WriteString("\n\n")
	}

	// 结构体注释
	tableComment := tableInfo.Comment
	if tableComment.Valid {
		writeBuilder.WriteString("// ")
		writeBuilder.WriteString(tableName)
		writeBuilder.WriteString("，")
		writeBuilder.WriteString(tableComment.String)
		writeBuilder.WriteString("\n")
	}

	// 结构体头
	structName := utils.ToHump(tableName, tableNamePre, settings.DatabaseSetting.TableNameSplit)
	writeBuilder.WriteString("type ")
	writeBuilder.WriteString(structName)
	writeBuilder.WriteString(" struct {\n")

	// 结构体中间的属性
	for index, tableColumn := range tableColumnSlice {

		// 属性名
		name := utils.ToHump(tableColumn.Name, settings.DatabaseSetting.ColumnNamePre, settings.DatabaseSetting.ColumnNameSplit)
		writeBuilder.WriteString("    ")
		writeBuilder.WriteString(name)

		// 属性类型
		writeBuilder.WriteString(" ")
		writeBuilder.WriteString(utils.Mapping(tableColumn.Type, tableColumn.NotNull))

		// 自定义注解
		poDbPre := settings.OutPutSetting.PoDbPre
		if poDbPre != "" {
			writeBuilder.WriteString(" ")
			writeBuilder.WriteString("`")
			writeBuilder.WriteString(poDbPre)
			writeBuilder.WriteString(":")
			writeBuilder.WriteString("\"")
			// 必须用原始的db字段名，转换前的
			writeBuilder.WriteString(tableColumn.Name)
			writeBuilder.WriteString("\"")
			writeBuilder.WriteString("`")
		}

		// 注释
		comment := tableColumn.Comment
		if comment.Valid {
			writeBuilder.WriteString(" // ")
			writeBuilder.WriteString(comment.String)
		}

		// 不是最后一个
		if index < len(tableColumnSlice)-1 {
			writeBuilder.WriteString("\n")
		}
	}

	// 结构体尾
	writeBuilder.WriteString("\n}\n")

	// 将拼接好的字符串写入文件中
	_, err = file.WriteString(writeBuilder.String())
	if err != nil {
		fmt.Println("文件写入失败：", err)
	} else {
		fmt.Println(savePathBuilder.String(), "文件生成完毕")
	}

	err = file.Close()
	if err != nil {
		fmt.Println("文件关闭失败：", err)
	}
}
